home *** CD-ROM | disk | FTP | other *** search
/ Workbench Design / WB Collection.iso / workbench werkzeuge / scherz programme / clicker / source / main.c < prev    next >
C/C++ Source or Header  |  1996-04-07  |  8KB  |  312 lines

  1. /*  File:         main.c
  2.  *  Created:      01-01-95
  3.  *  Updated:      30-12-95
  4.  *  Version:      1.00
  5.  *  Project:      Clicker
  6.  *  Owner:        Jeroen Vermeulen
  7.  *  Requirements: KickStart V39+
  8.  *  Legal:        PD
  9.  *  Status:       Release
  10.  */
  11.  
  12. char verstr[]="$VER: Clicker 1.0 (30.12.95) Jeroen Vermeulen",
  13.      descrp[]="Clicker 1.0 - Public Domain";
  14.  
  15. /* TODO:
  16.  *      Prefs save option!
  17.  *      Add note names to frequency display
  18.  *      Improve sound quality (longer sample perhaps?)
  19.  */
  20.  
  21. #include <proto/exec.h>
  22. #include <exec/libraries.h>
  23. #include <exec/devices.h>
  24. #include <exec/memory.h>
  25. #include <proto/dos.h>
  26. #include <proto/icon.h>
  27. #include <proto/utility.h>
  28. #include <proto/commodities.h>
  29. #include <proto/gadtools.h>
  30. #include <proto/alib.h>
  31. #include <intuition/gadgetclass.h>
  32.  
  33. #include "main.h"
  34. #include "broker.h"
  35. #include "prefs.h"
  36. #include "sound.h"
  37. #include "gui.h"
  38.  
  39.  
  40. STRPTR  AllocFailMsgPort = "Unable to set up message port!\n";
  41.  
  42. static STRPTR
  43.         Break_Exit       = "**BREAK** -- Clicker removed\n";
  44.  
  45. /* EventLoop():
  46.  * This is where our commodity does its work. This function receives
  47.  * CX messages and acts on them, mostly by making noises.
  48.  * If anything should go wrong, errptr is directed to an error string
  49.  * and the return value is set accordingly. If all is well, this should
  50.  * be RETURN_OK.
  51.  */
  52. static int EventLoop(STRPTR                *const errptr,
  53.                      CxObj                 *const brokerobj,
  54.                      struct MsgPort        *const cxport,
  55.                      struct IOAudio        *const soundrequest,
  56.                      struct WindowContext  *const PrefsWin)
  57. {
  58.   const ULONG  waitmask = SIGBREAKF_CTRL_C | (1<<(cxport->mp_SigBit));
  59.   /* --- */
  60.  
  61.   for (;;)
  62.   {
  63.     struct Message *msg;
  64.     BOOL            closewin = FALSE;
  65.     const  ULONG gotsig = Wait(waitmask|(PrefsWin->SigMask));
  66.  
  67.     /* --- */
  68.  
  69.     if (gotsig & SIGBREAKF_CTRL_C)
  70.     {
  71.       *errptr = Break_Exit;
  72.       return(RETURN_WARN);
  73.     }
  74.  
  75.     while ((msg = GetMsg(cxport)))
  76.     {
  77.       CxMsg *const cxmsg = (CxMsg *)msg;
  78.       ULONG msgid    = CxMsgID(cxmsg);
  79.       ULONG msgtype  = CxMsgType(cxmsg);
  80.       BOOL  clicknow = FALSE;
  81.  
  82.       switch (msgtype)
  83.       {
  84.         case CXM_COMMAND: switch (msgid)
  85.           {
  86.             case CXCMD_DISABLE:
  87.                   ActivateCxObj(brokerobj,FALSE);
  88.             break;
  89.  
  90.             case CXCMD_ENABLE:
  91.                   ActivateCxObj(brokerobj,TRUE);
  92.             break;
  93.  
  94.             case CXCMD_KILL:
  95.                   return(RETURN_OK);
  96.  
  97.             case CXCMD_APPEAR:
  98.             case CXCMD_UNIQUE:
  99.                   ShowWindow(errptr,PrefsWin);
  100.             break;
  101.  
  102.             case CXCMD_DISAPPEAR:
  103.                   closewin = TRUE;
  104.             break;
  105.           }
  106.         break;
  107.  
  108.         case CXM_IEVENT:
  109.         {
  110.           struct InputEvent *const ievent =
  111.                 (struct InputEvent *)CxMsgData(cxmsg);
  112.  
  113.           if (!(ievent->ie_Code & IECODE_UP_PREFIX))
  114.           {
  115.             switch (ievent->ie_Class)
  116.             {
  117. #ifndef   NOCLICKMOUSE
  118.               case IECLASS_RAWMOUSE:
  119.                 clicknow = ClickPrefs.ClickMouse;
  120.               break;
  121. #endif /* NOCLICKMOUSE */
  122.  
  123.               case IECLASS_RAWKEY:
  124.                 clicknow = TRUE;
  125.               break;
  126.  
  127.               default:
  128.               break;
  129.             }
  130.           }
  131.         }
  132.         break;
  133.  
  134.         default:
  135.         break;
  136.       }
  137.       ReplyMsg(msg);
  138.       if (clicknow) KeyClick(soundrequest);
  139.     }
  140.     if (PrefsWin->Shown)
  141.     {
  142.       struct IntuiMessage *imsg;
  143.       /* --- */
  144.       while ((imsg = GT_GetIMsg(PrefsWin->Win->UserPort)))
  145.       {
  146.         const ULONG imsg_Class = imsg->Class;
  147.         const UWORD imsg_Code  = imsg->Code;
  148.         struct Gadget *const g = imsg->IAddress;
  149.  
  150.         /* --- */
  151.  
  152.         GT_ReplyIMsg(imsg);
  153.  
  154.         switch (imsg_Class)
  155.         {
  156.           case IDCMP_GADGETDOWN:
  157.           case IDCMP_GADGETUP:
  158.           case IDCMP_MOUSEMOVE:
  159.             switch (g->GadgetID)
  160.             {
  161.               case mygadget_volume:
  162.                 ClickPrefs.volume = imsg_Code;
  163.                 ClickPrefs.newsettings = TRUE;
  164.               break;
  165.  
  166.               case mygadget_cycles:
  167.                 ClickPrefs.cycles = imsg_Code;
  168.                 ClickPrefs.newsettings = TRUE;
  169.               break;
  170.  
  171.               case mygadget_period:
  172.                 ClickPrefs.period = SliderToPeriod(imsg_Code);
  173.                 ClickPrefs.newsettings = TRUE;
  174.               break;
  175.  
  176. #ifndef   NOCLICKMOUSE
  177.               case mygadget_clickmouse:
  178.                 ClickPrefs.ClickMouse = (g->Flags & GFLG_SELECTED);
  179.               break;
  180. #endif /* NOCLICKMOUSE */
  181.  
  182.               default:
  183.               break;
  184.             }
  185.           break;
  186.  
  187.           case IDCMP_CLOSEWINDOW:
  188.             closewin = TRUE;
  189.           break;
  190.  
  191.           case IDCMP_REFRESHWINDOW:
  192.              GT_BeginRefresh(PrefsWin->Win);
  193.              GT_EndRefresh(PrefsWin->Win,TRUE);
  194.           break;
  195.  
  196.           default:
  197.           break;
  198.         }
  199.       }
  200.       if (closewin) HideWindow(PrefsWin);
  201.     }
  202.   }
  203. }
  204.  
  205.  
  206. /* MatchStr():
  207.  * Boolean frontend for stricmp().  Returns TRUE if the strings pointed to by
  208.  * its arguments are identical (case-insensitive comparison), or FALSE if not.
  209.  */
  210. static BOOL MatchStr(const STRPTR a, const STRPTR b)
  211. {
  212.   return (BOOL)(Stricmp((UBYTE *)a,(UBYTE *)b)==0);
  213. }
  214.  
  215. /* BoolAttr():
  216.  * Returns whether a tooltype string should be interpreted as TRUE.  Defaults to
  217.  * FALSE if no string is given, but TRUE if the string is empty.
  218.  * Hopefully this behaviour allows tooltypes to be set without arguments.
  219.  */
  220. static BOOL BoolAttr(const UBYTE *const value)
  221. {
  222.   UBYTE *val = (UBYTE *)value;
  223.   if (val && (!*val || MatchStr(val,"TRUE") || MatchStr(val,"YES") ||
  224.       MatchStr(val,"ON")))
  225.     return TRUE;
  226.   else return FALSE;
  227. }
  228.  
  229.  
  230. int main(LONG argc, UBYTE **argv)
  231. {
  232.   int      returnval = RETURN_FAIL;
  233.   STRPTR   error  = NULL;
  234.   BYTE     CX_Priority = 0;
  235.   BOOL     cx_popup = FALSE;
  236.  
  237.   struct NewBroker *mybroker;
  238.   struct IOAudio   *soundrequest;
  239.  
  240.   /* There may already be another copy of Clicker running, so prefs settings are
  241.    * gathered into a temporary struct to prevent them from overwriting those of
  242.    * the active Clicker.
  243.    */
  244.   struct SoundSettings TempPrefs;
  245.   /* --- */
  246.  
  247.   soundrequest = CreateSample(&error);
  248.   if (soundrequest)
  249.   {
  250.     if ((IconBase = OpenLibrary("icon.library",36)))
  251.     {
  252.       UBYTE **ToolTypes;
  253.       /* --- */
  254.       if ((ToolTypes=ArgArrayInit(argc,argv)))
  255.       {
  256.         /* Read tooltype settings for click sound
  257.          */
  258.         TempPrefs.period = HertzToPeriod(ArgInt(ToolTypes,"PITCH",739));
  259.         TempPrefs.volume = ArgInt(ToolTypes,"VOLUME",(ULONG)ClickPrefs.volume);
  260.         TempPrefs.cycles = ArgInt(ToolTypes,"LENGTH",(ULONG)ClickPrefs.cycles);
  261.  
  262. #ifdef    NOCLICKMOUSE
  263.         TempPrefs.ClickMouse = FALSE;
  264. #else  /* NOCLICKMOUSE */
  265.         TempPrefs.ClickMouse = BoolAttr(ArgString(ToolTypes,"CLICKMOUSE","NO"));
  266. #endif /* NOCLICKMOUSE */
  267.  
  268.         cx_popup             = BoolAttr(ArgString(ToolTypes,"CX_POPUP","NO"));
  269.         ArgArrayDone();
  270.       }
  271.       CloseLibrary(IconBase);
  272.     }
  273.  
  274.     /* Unpleasantness happens if LENGTH is set to zero.  Checking for this is
  275.      * worth the bother if you ask me.
  276.      */
  277.     if (!TempPrefs.cycles) TempPrefs.cycles = 1;
  278.  
  279.     TempPrefs.newsettings = TRUE;
  280.  
  281.     mybroker = MakeBroker(&error, CX_Priority);
  282.     if (mybroker)
  283.     {
  284.       CxObj  *brokerobj;
  285.       /* --- */
  286.       if ((brokerobj = SetupBroker(&error,mybroker)))
  287.       {
  288.         struct WindowContext *PrefsWin;
  289.         /* --- */
  290.         if ((PrefsWin = MakeWindow(&error,cx_popup)))
  291.         {
  292.           CopySoundPrefs(&TempPrefs,&ClickPrefs);
  293.           ActivateCxObj(brokerobj,TRUE);
  294.           returnval = EventLoop(&error, brokerobj, mybroker->nb_Port,
  295.                                 soundrequest, PrefsWin);
  296.           ActivateCxObj(brokerobj,FALSE);
  297.           DestroyWindow(PrefsWin);
  298.         }
  299.         DeleteCxObjAll(brokerobj);
  300.       }
  301.       KillBroker(mybroker);
  302.     }
  303.     DeleteSample(soundrequest);
  304.   }
  305.  
  306.   if (error)
  307.   {
  308.     PutStr(error);
  309.   }
  310.   return(returnval);
  311. }
  312.